package com.happy.xiao.common.utils;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.happy.xiao.common.base.MyErrorException;
import sun.misc.BASE64Encoder;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Util {
    public static final String LINE_SEPARATOR = System
            .getProperty("line.separator");
    public static final DecimalFormat df = new DecimalFormat("00");

    /**
     * @param s
     * @return
     */
    public static int getFirstNumIndex(String s) {
        if (s == null)
            return -1;
        for (int i = 0; i < s.length(); i++) {
            if (Character.isDigit(s.charAt(i))) {
                return i;
            }
        }
        return -1;
    }

    public static int getFirstNotNumIndex(String s) {
        if (s == null)
            return -1;
        for (int i = 0; i < s.length(); i++) {
            if (!Character.isDigit(s.charAt(i))) {
                return i;
            }
        }
        return -1;
    }

    public static String getAirways(String flight) {
        if (flight == null)
            return "";
        int p = getFirstNumIndex(flight);
        if (p != -1)
            return flight.substring(0, p);
        return "";
    }

    public static int getFlightNo(String flight) {
        if (flight == null)
            return -1;
        int p = getFirstNumIndex(flight);
        if (p != -1)
            return new Integer(flight.substring(p)).intValue();
        return -1;
    }

    /**
     * @param source
     * @param beginLine
     * @param lineNum
     * @return
     */
    public static String getNumLineString(String source, int beginLine,
                                          int lineNum) {

        String s = new String(source);
        int begin = 0, end = 0;
        for (int i = 0; i < beginLine; i++) {
            int index = s.indexOf(LINE_SEPARATOR);
            if (index != -1) {
                s = s.substring(index + 1);
                begin += index + 1;
            }
        }
        s = source.substring(begin + 1);
        for (int i = 0; i < lineNum; i++) {
            int index = s.indexOf(LINE_SEPARATOR);
            if (index != -1) {
                s = s.substring(index + 1);
                end += index + 1;
            }
        }
        end += begin;
        return source.substring(begin, end);
    }

    /**
     * @param s
     * @param split
     * @param isL
     * @return
     */
    public static String[] getPlnLines(String s, String split, boolean isL) {
        List l = new ArrayList();
        String[] splits = s.split(split);// s.split(LINE_SEPARATOR + "//d{2}");
        for (int i = 1; i < splits.length; i++) {
            String s1 = splits[i].trim();
            if (s1.length() < 15)
                continue;
            // ��) MF ���⴦��
            int pp2 = s1.indexOf(")");
            if (pp2 > 0 && pp2 <= 3 && Character.isDigit(s1.charAt(0)))
                s1 = s1.substring(pp2 + 1);
            if (pp2 > 0 && pp2 <= 3 && s1.charAt(0) == '(')
                s1 = s1.substring(pp2 + 1);
            // �����AWY���⴦��
            int p = s1.indexOf("AWY");
            if (p != -1) {
                String s12 = s1.replaceAll("\\s", " ").trim();
                if (Character.isDigit(s12.charAt(s12.length() - 1))) {
                    s12 = s12.substring(0, s12.length() - 2).trim();
                }
                l.add(s12);
                continue;
            }
            String[] s11 = getNotNullLines(s1);
            for (int j = 0; j < s11.length; j++) {
                if (s11[j].length() < 20)
                    continue;
                String s12 = s11[j].trim();
                // L02
                if (isL) {
                    int p0 = getFirstNotNumIndex(s12);
                    if (p0 != -1)
                        s12 = s12.substring(p0).trim();
                }
                l.add(s12);
            }
        }
        return (String[]) l.toArray(new String[0]);
    }

    public static String[] getNotNullLines(String s) {
        List l = new ArrayList();
        String[] strs = s.split("\n");
        for (int i = 0; i < strs.length; i++) {
            if (trim(strs[i]).length() > 20) {
                l.add(strs[i]);
            }
        }
        // return l;
        return (String[]) l.toArray(new String[0]);
    }

    public static String trim(String s) {
        if (s == null)
            return s;
        String s1 = s.trim();
        s1.replaceAll("\\s", "");
        return s1;
    }

    /**
     * �õ�����ʱ�� gmt Сʱ+8
     *
     * @param gmtTime ������4�����ֵ��ַ�
     * @return
     */
    public static String getBJTime(String gmtTime) {
        String s = trim(gmtTime);
        if (s.length() != 4)
            return null;
        String hour = s.substring(0, 2);
        String minute = s.substring(2);
        int h = Integer.valueOf(hour).intValue();
        h = (h + 8) % 24;

        return df.format(h) + minute;
    }

    /**
     * @param time    ��ʼʱ�� 4�������ַ�
     * @param flyTime ����ʱ�� 4�������ַ�
     * @return
     */
    public static String getTime(String time, String flyTime) {
        String t = trim(time);
        String ft = trim(flyTime);
        if (time == null || time.length() != 4)
            return null;
        if (flyTime == null)
            return null;
        String hour = t.substring(0, 2);
        String minute = t.substring(2);

        String hour1 = ft.substring(0, 2);
        String minute1 = ft.substring(2);

        int h = Integer.valueOf(hour).intValue()
                + Integer.valueOf(hour1).intValue();
        int m = Integer.valueOf(minute).intValue()
                + Integer.valueOf(minute1).intValue();

        h = h + m / 60;
        m = m % 60;
        h = h % 24;
        return df.format(h) + df.format(m);

    }

    public static String transformTime(long flyTime) {
        String hour = null;
        String minute = null;
        hour = String.valueOf(flyTime / 60);
        minute = String.valueOf(flyTime % 60);
        hour = hour.length() == 1 ? "0" + hour : hour;
        minute = minute.length() == 1 ? "0" + minute : minute;

        return hour + minute;
    }

    /**
     * �����Сдת��Ϊ����д ��param input
     */
    public static String numtochinese(String input) {
        String s1 = "��Ҽ��������½��ƾ�";
        String s4 = "�ֽ���Ԫʰ��Ǫ��ʰ��Ǫ��ʰ��Ǫ";
        String temp = "";
        String result = "";
        // if (StringUtils.isBlank(input))
        // return "";
        temp = input.trim();
        float f;
        try {
            f = Float.parseFloat(temp);

        } catch (Exception e) {
            return "�����ִ��������ִ�ֻ�ܰ��������ַ�?'��?'��'.')�������ִ����ֻ�ܾ�ȷ��Ǫ�ڣ�С���ֻ����λ��";
        }

        int len = 0;
        if (temp.indexOf(".") == -1)
            len = temp.length();
        else
            len = temp.indexOf(".");
        if (len > s4.length() - 3)
            return ("�����ִ����ֻ�ܾ�ȷ��Ǫ�ڣ�С���ֻ����λ��");
        int n1, n2 = 0;
        String num = "";
        String unit = "";

        for (int i = 0; i < temp.length(); i++) {
            if (i > len + 2) {
                break;
            }
            if (i == len) {
                continue;
            }
            n1 = Integer.parseInt(String.valueOf(temp.charAt(i)));
            num = s1.substring(n1, n1 + 1);
            n1 = len - i + 2;
            unit = s4.substring(n1, n1 + 1);
            result = result.concat(num).concat(unit);
        }
        if ((len == temp.length()) || (len == temp.length() - 1))
            result = result.concat("��");
        if (len == temp.length() - 2)
            result = result.concat("���");
        return result;
    }

    /**
     * ��ʽ�����֣�֧���������룬��ָ��С��λ��
     *
     * @param bNumber
     * @param dotLength
     * @return ָ��С��λ������ֵ��ַ�
     */
    public static String formatNumber(BigDecimal bNumber, int dotLength) {
        if (bNumber == null) {
            return formatNumber(new BigDecimal("0"), dotLength);
        }
        return bNumber.setScale(dotLength, BigDecimal.ROUND_HALF_UP).toString();
    }

    public static String readFile(String filePath) {
        StringBuffer inputBuffer = new StringBuffer();
        try {
            FileInputStream in = new FileInputStream(filePath);
            int newData = 0;
            while (newData != -1) {
                try {
                    newData = in.read();
                    if (newData == -1) {
                        break;
                    }
                    inputBuffer.append((char) newData);
                } catch (IOException ex) {
                    System.err.println(ex);
                }
            }

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return inputBuffer.toString();
    }

    /**
     * 生成MD5加密信息
     *
     * @param str 要加密的String
     * @return 生成的MD5信息
     */
    public static String getMD5(String str) {
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.reset();
            messageDigest.update(str.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            System.out.println("NoSuchAlgorithmException caught!");
            System.exit(-1);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        byte[] byteArray = messageDigest.digest();
        StringBuffer md5StrBuff = new StringBuffer();
        for (int i = 0; i < byteArray.length; i++) {
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1) {
                md5StrBuff.append("0").append(
                        Integer.toHexString(0xFF & byteArray[i]));
            } else {
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
            }
        }
        return md5StrBuff.toString();
    }


    /**
     * 将UTF-8编码的字符串转换为GB2312
     *
     * @param str
     * @return
     */
    public static String utf8ToGb2312(String str) {
        byte[] sour;
        String result = null;
        try {
            sour = str.getBytes();
            result = new String(sour, "gb2312");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return result;
    }

    public static String gb2312ToUtf8(String str) {
        byte[] sour;
        String result = null;
        try {
            sour = str.getBytes("gb2312");
            result = new String(sour, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return result;
    }

    public static String isoToUtf8(String str) {
        byte[] sour;
        String result = null;
        try {
            sour = str.getBytes("ISO8859-1");
            result = new String(sour, "utf-8");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return result;
    }

    public static String gbkToUtf82(String str) {
        String fullStr = null;
        try {
            byte[] fullByte = gbk2utf8(str);
            fullStr = new String(fullByte, "UTF-8");

        } catch (Exception e) {
            e.printStackTrace();
        }
        return fullStr;
    }

    public static byte[] gbk2utf8(String chenese) {

        // Step 1: 得到GBK编码下的字符数组，一个中文字符对应这里的一个c[i]
        char c[] = chenese.toCharArray();

        // Step 2: UTF-8使用3个字节存放一个中文字符，所以长度必须为字符的3倍
        byte[] fullByte = new byte[3 * c.length];

        // Step 3: 循环将字符的GBK编码转换成UTF-8编码
        for (int i = 0; i < c.length; i++) {

            // Step 3-1：将字符的ASCII编码转换成2进制值
            int m = (int) c[i];
            String word = Integer.toBinaryString(m);

            // Step 3-2：将2进制值补足16位(2个字节的长度)
            StringBuffer sb = new StringBuffer();
            int len = 16 - word.length();
            for (int j = 0; j < len; j++) {
                sb.append("0");
            }
            // Step 3-3：得到该字符最终的2进制GBK编码
            // 形似：1000 0010 0111 1010
            sb.append(word);

            // Step 3-4：最关键的步骤，根据UTF-8的汉字编码规则，首字节
            // 以1110开头，次字节以10开头，第3字节以10开头。在原始的2进制
            // 字符串中插入标志位。最终的长度从16--->16+3+2+2=24。
            sb.insert(0, "1110");
            sb.insert(8, "10");
            sb.insert(16, "10");

            // Step 3-5：将新的字符串进行分段截取，截为3个字节
            String s1 = sb.substring(0, 8);
            String s2 = sb.substring(8, 16);
            String s3 = sb.substring(16);

            // Step 3-6：最后的步骤，把代表3个字节的字符串按2进制的方式
            // 进行转换，变成2进制的整数，再转换成16进制值
            byte b0 = Integer.valueOf(s1, 2).byteValue();
            byte b1 = Integer.valueOf(s2, 2).byteValue();
            byte b2 = Integer.valueOf(s3, 2).byteValue();

            // Step 3-7：把转换后的3个字节按顺序存放到字节数组的对应位置
            byte[] bf = new byte[3];
            bf[0] = b0;
            bf[1] = b1;
            bf[2] = b2;

            fullByte[i * 3] = bf[0];
            fullByte[i * 3 + 1] = bf[1];
            fullByte[i * 3 + 2] = bf[2];

            // Step 3-8：返回继续解析下一个中文字符
        }
        return fullByte;
    }

    public static String md5EncryptAndBase64(String str) {
        return encodeBase64(md5Encrypt(str));
    }

    private static byte[] md5Encrypt(String encryptStr) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(encryptStr.getBytes("utf8"));
            return md5.digest();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String encodeBase64(byte[] b) {
        BASE64Encoder base64Encode = new BASE64Encoder();
        String str = base64Encode.encode(b);
        return str;
    }

    public static String gb2312ReplaceUtf8(String xmlString) {
        String tempXmlString = xmlString;
        String regEx = "encoding=(.+?)\'";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(xmlString);
        int i = 0;
        while (m.find()) {
            String subString = m.group(0);
            tempXmlString = tempXmlString.replace(subString, "encoding='utf-8'");
            i++;
        }
        return tempXmlString.replaceAll("DCSI", "DCS");
    }

    public static String UTF8ReplaceUtf8(String xmlString) {
        String tempXmlString = xmlString;
        String regEx = "encoding=(.+?)\'";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(xmlString);
        int i = 0;
        while (m.find()) {
            String subString = m.group(0);
            tempXmlString = tempXmlString.replace(subString, "encoding='utf-8'");
            i++;
        }
        return tempXmlString.replaceAll("DCSI", "DCS");
    }

    public static Timestamp stringToTimeStamp(String dateTime) {
        Timestamp ts = null;
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        format.setLenient(false);
        try {
            ts = new Timestamp(format.parse(dateTime).getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return ts;
    }

    public static Timestamp stringToTimeStamp2(String dateTime) {
        Timestamp ts = null;
        DateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        format.setLenient(false);
        try {
            ts = new Timestamp(format.parse(dateTime).getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return ts;
    }

    /**
     * 将JAVA对象转换成JSON字符串
     *
     * @param obj
     * @return
     */
    public static String ObjectToJson(Object obj) {
        String jsonString = null;
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.setSerializationInclusion(Include.NON_NULL);
            jsonString = mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return jsonString;
    }

    /**
     * 将JSON字符串转换成JAVA对象
     *
     * @param obj
     * @param jsonString
     * @return
     * @throws JsonParseException
     * @throws JsonMappingException
     * @throws IOException
     */
    public static Object JsonToObject(Class<?> obj, String jsonString) throws JsonParseException, JsonMappingException, IOException {
        ObjectMapper mapper = new ObjectMapper();

        Object returnObj = mapper.readValue(jsonString, obj);

        return returnObj;
    }

    public static <T> T jsonStringToObject(Class<T> obj, String jsonString) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        T returnObj = mapper.readValue(jsonString, obj);

        return returnObj;
    }


    public static <T> T JsonToObject(TypeReference typeReference, String jsonString) {

        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.readValue(jsonString, typeReference);
        } catch (Exception e) {
            throw new MyErrorException("格式化参数异常", -1);

        }
    }


    /**
     * 生成token字符串
     *
     * @return
     */
    public static String getToken() {
        String token = UUID.randomUUID().toString();
        token = getMD5(token);

        return token;
    }


    public static Date getNowDateTime() {
        Calendar calendar = Calendar.getInstance(Locale.CHINESE);

        return calendar.getTime();
    }

    /**
     * 获取当前时间，并转换为UNIX_TIME格式
     *
     * @return
     * @throws ParseException
     */
    public static int getUnixTimeFromNow() throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Date date = getNowDateTime();
        Long dateTime = (sdf.parse(sdf.format(date))).getTime() / 1000;


        return dateTime.intValue();
    }

    /**
     * 获取指定时间，并转换为UNIX_TIME格式
     *
     * @return
     * @throws ParseException
     */
    public static int getUnixTime(Date date) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Long dateTime = (sdf.parse(sdf.format(date))).getTime() / 1000;


        return dateTime.intValue();
    }

    /**
     * 获取当日的凌晨0点
     *
     * @return
     */
    public static Date getToDayBegin() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date zero = calendar.getTime();

        return zero;
    }

    /**
     * 获取次日凌晨零点
     *
     * @return
     */
    public static Date getToDayEnd() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        calendar.add(Calendar.SECOND, 0);

        Date end = calendar.getTime();

        return end;
    }

    /**
     * 取结算的年度,当日的上个月所在年度
     *
     * @return
     */
    public static Integer getBalanceYear() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());//设置当前日期
        calendar.add(Calendar.MONTH, -1);//月份减一
        Integer year = calendar.get(Calendar.YEAR);
        return year;
    }

    /**
     * 获取结算的月份，当日上个月
     *
     * @return
     */
    public static Integer getBalanceMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());//设置当前日期
        calendar.add(Calendar.MONTH, -1);//月份减一
        Integer month = calendar.get(Calendar.MONTH) + 1;
        return month;
    }

    /**
     * 获取当前日期的前一天
     *
     * @return
     */
    public static Integer getPreday() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());//设置当前日期
        calendar.add(Calendar.DAY_OF_MONTH, -1);//日期减一
        Integer day = calendar.get(Calendar.DAY_OF_MONTH);
        return day;
    }

    /**
     * 获取当前日期的前一天所在年度
     *
     * @return
     */
    public static Integer getPredayYear() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());//设置当前日期
        calendar.add(Calendar.DAY_OF_MONTH, -1);//日期减一
        Integer year = calendar.get(Calendar.YEAR);
        return year;
    }

    /**
     * 获取当前日期的前一天所在月度
     *
     * @return
     */
    public static Integer getPredayMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());//设置当前日期
        calendar.add(Calendar.DAY_OF_MONTH, -1);//日期减一
        Integer year = calendar.get(Calendar.MONTH) + 1;
        return year;
    }


    /**
     * 获取当前日期
     *
     * @return
     */
    public static Integer getNowday() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());//设置当前日期
        calendar.add(Calendar.DAY_OF_MONTH, 0);
        Integer day = calendar.get(Calendar.DAY_OF_MONTH);
        return day;
    }

    /**
     * 获取当前日期的所在年度
     *
     * @return
     */
    public static Integer getNowYear() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());//设置当前日期
        calendar.add(Calendar.DAY_OF_MONTH, 0);
        Integer year = calendar.get(Calendar.YEAR);
        return year;
    }

    /**
     * 获取当前日期的所在月度
     *
     * @return
     */
    public static Integer getNowMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());//设置当前日期
        calendar.add(Calendar.DAY_OF_MONTH, 0);
        Integer year = calendar.get(Calendar.MONTH) + 1;
        return year;
    }

    /**
     * 获取格式化当前时间
     *
     * @param date
     * @return
     */
    public static String formateDtae(Date date) {
        //SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        String format = sdf.format(new Date());
        return format;
    }

    public static String formateDate(Date date) {
        //SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String format = sdf.format(new Date());
        return format;
    }

    /**
     * 产生num位的随机数
     *
     * @param num
     * @return
     */
    public static String getRandByNum(int num) {
        String length = "1";
        for (int i = 0; i < num; i++) {
            length += "0";
        }
        Random rad = new Random();
        String result = rad.nextInt(Integer.parseInt(length)) + "";
        if (result.length() != num) {
            return getRandByNum(num);
        }
        return result;
    }

    public static void removeDuplicateString(List<String> list) {
        LinkedHashSet<String> set = new LinkedHashSet<>(list.size());
        set.addAll(list);
        list.clear();
        list.addAll(set);
    }

    public static void removeDuplicateInt(List<Integer> list) {
        LinkedHashSet<Integer> set = new LinkedHashSet<>(list.size());
        set.addAll(list);
        list.clear();
        list.addAll(set);
    }
}
